文章目录
预备知识递归地打印父类getSuperclass()Class的newInstance方法操作私有成员(取值,赋值)调用私有方法创建private内部类的实例
预备知识
通过 实例.getClass() 返回实例的运行时类类型的Class引用。通过 类名.class 可以获得Class引用(前提是你可以import这个类,好处是使用.class来创建对Class对象的引用时,不会自动地初始化该Class对象)。通过 Class.forName(类名的全称) 也可以获得Class引用。其方法声明为public static Class forName(String className),注意泛型为?。
递归地打印父类getSuperclass()
package com.prac;
class A{}
class B extends A {}
class C extends B {}
public class testRecur {
static void printInfo(Class cc){
System.out.println("name: "+cc.getName());
System.out.println("is interface? "+cc.isInterface());
System.out.println("simple name: "+cc.getSimpleName());
System.out.println("canonical name: "+cc.getCanonicalName());
System.out.println();
}
static void f(Class c){
printInfo(c);
try{
f(c.getSuperclass());
}catch(Exception e){
}
}
public static void main(String[] args) {
Class c = null;
try{
c = Class.forName("com.prac.C");
//c = C.Class;也能有同样效果
f(c);
}catch(ClassNotFoundException e){}
}
}
打印结果如下:
name: com.prac.C
is interface? false
simple name: C
canonical name: com.prac.C
name: com.prac.B
is interface? false
simple name: B
canonical name: com.prac.B
name: com.prac.A
is interface? false
simple name: A
canonical name: com.prac.A
name: java.lang.Object
is interface? false
simple name: Object
canonical name: java.lang.Object
很可惜,getSuperclass这个方法只能看到native,方法声明为@HotSpotIntrinsicCandidate public native Class c = C.class时,newInstance返回的对象的类型为Object。当声明初始化语句为Class制定的泛型是?(newInstance的方法声明为public T newInstance(Object ... initargs),从这里可以看出返回类型为T,但由于创建时指定的是?),所以con.newInstance(out)只能返回Object引用,虽然你已经创建了normalInner的实例。现在有Object引用指向了normalInner的实例,通过获得Field,一样可以获得实例的成员变量。(这点很关键,因为原来我以为这种引用是无法获得成员的,但反射可能只跟对象的RTTI有关,无所谓引用是不是基类Object)
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Field;
import com.prac.outer;
public class testInner {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
outer out = new outer();
Class staticClazz = null;
try {
staticClazz = Class.forName("com.prac.outer$staticInner");
System.out.println(staticClazz.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Constructor con = staticClazz.getDeclaredConstructor();
con.setAccessible(true);
Object obj = con.newInstance();
try {
Field field = staticClazz.getDeclaredField("j");
field.setAccessible(true);
System.out.println(field.get(obj));
} catch (NoSuchFieldException e) {
System.out.println("get field failed");
e.printStackTrace();
}
}
}
同样,对私有静态内部类进行测试。打印结果:
com.prac.outer$staticInner
2
|